﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//#if !BclAsync40
//using TaskEx = System.Threading.Tasks.Task;
#if BclAsync40
using static System.Threading.Tasks.TaskEx;
#else
using static System.Threading.Tasks.Task;
#endif

namespace OmniKits.Async
{
    public class RetryAsync
    {
#pragma warning disable 1591

        public static async Task DoRetry(Func<Task> action, int maxRetry, TimeSpan delay, TimeSpan? delayIncrement = null, TimeSpan? maxDelay = null)
        {
            if (delayIncrement == null)
                delayIncrement = delay;

            if (maxDelay == null)
                maxDelay = TimeSpan.MaxValue;

            int retry = 0;

            for (; ;)
            {
                try
                {
                    await action();
                    return;
                }
                catch
                {
                    if (retry == maxRetry)
                        throw;
                }

                await Delay(delay);

                if (delay < maxDelay.Value)
                {
                    delay += delayIncrement.Value;
                    if (delay > maxDelay.Value)
                        delay = maxDelay.Value;
                }
            }
        }

        public static async Task<T> DoRetry<T>(Func<Task<T>> func, int maxRetry, TimeSpan delay, TimeSpan? delayIncrement = null, TimeSpan? maxDelay = null)
        {
            if (delayIncrement == null)
                delayIncrement = delay;

            if (maxDelay == null)
                maxDelay = TimeSpan.MaxValue;

            int retry = 0;

            for (; ;)
            {
                try
                {
                    return await func();
                }
                catch
                {
                    if (retry == maxRetry)
                        throw;
                }

                await Delay(delay);

                if (delay < maxDelay.Value)
                {
                    delay += delayIncrement.Value;
                    if (delay > maxDelay.Value)
                        delay = maxDelay.Value;
                }
            }
        }
    }
}
